package com.xpec.cipher.h5handler;

import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPublicKey;
import java.util.Arrays;
import java.util.Random;

import com.xpec.cipher.CipherConnectionConstant;
import com.xpec.cipher.CipherHandler;
import com.xpec.cipher.handler.CipherConnectionPacketHandler;
import com.xpec.cipher.tals.TalsConstance;
import com.xpec.cipher.tals.record.RSAPublicKeyRecord;
import com.xpec.cipher.tals.record.ServerHelloRecord;
import com.xpec.net.xnetty.h5cihper.H5BaseCipherChannelHandler;

public class H5ServerHandShakeHandler implements CipherConnectionPacketHandler
{
	private Random random = new Random(System.currentTimeMillis());

	private static KeyPairGenerator keyPairGenerator;

	static
	{
		try
		{
			keyPairGenerator = KeyPairGenerator.getInstance("RSA");
			// key size 2048b
			keyPairGenerator.initialize(new java.security.spec.RSAKeyGenParameterSpec(
				TalsConstance.RSA_MODULUS_SIZE * 8, BigInteger.valueOf(65537)));
		}
		catch (NoSuchAlgorithmException e)
		{
			e.printStackTrace();
		}
		catch (InvalidAlgorithmParameterException e)
		{
			e.printStackTrace();
		}
	}

	private static KeyPair keyPair  = keyPairGenerator.generateKeyPair();;

	@Override
	public void receiveHandle(CipherHandler cipherHandler)
	{
		// 接收到的是Client发过来的HandShake包
		int contentType = cipherHandler.readUnsignedByteFromRealContent();
		if (contentType == TalsConstance.CONTENT_TYPE_HAND_SHAKE)
		{
			int handShakeType = cipherHandler.readUnsignedByteFromRealContent();
			if (handShakeType == TalsConstance.HAND_SHAKE_TYPE_CLIENT_HELLO)
			{
				// 读取client hello
				byte[] clientRandom = new byte[TalsConstance.CLIENT_HELLO_SIZE];
				cipherHandler.readByteFromRealContent(clientRandom);

				// 记录一下client的随机数
				cipherHandler.setParameter(CipherConnectionConstant.PARA_KEY_CLIENT_RANDOM,
					clientRandom);

				// 随机生成并发送server hello
				byte[] serverRandom = new byte[TalsConstance.SERVER_HELLO_SIZE];
				random.nextBytes(serverRandom);

				// 记录一下server的随机数
				cipherHandler.setParameter(CipherConnectionConstant.PARA_KEY_SERVER_RANDOM, serverRandom);

				// 发送Server的HandShakeRecord
				ServerHelloRecord helloRecord = new ServerHelloRecord(serverRandom);
				// 直接发送给外层的链条了
				cipherHandler.sendData(helloRecord.resolve(), false);
				
				// filterChain.packetSend(helloPacket);

				// 生成并发送rsa public key
				//keyPair = keyPairGenerator.generateKeyPair();
				
				// 这个keyPair要存到session里，后面的Handler要用的！
				cipherHandler.setParameter(CipherConnectionConstant.PARA_KEY_KEY_PAIR,
					keyPair);
				byte[] temp = ((RSAPublicKey) keyPair.getPublic()).getModulus().toByteArray();
				byte[] publicModulus = null;
				if (temp.length > TalsConstance.RSA_MODULUS_SIZE)
				{
					publicModulus = Arrays.copyOfRange(temp, temp.length
							- TalsConstance.RSA_MODULUS_SIZE, temp.length);
				}
				else
				{
					publicModulus = temp.clone();
				}
				temp = ((RSAPublicKey) keyPair.getPublic()).getPublicExponent().toByteArray();
				byte[] exp = new byte[TalsConstance.RSA_EXP_SIZE];
				if (temp.length < TalsConstance.RSA_EXP_SIZE)
				{
					for (int i = exp.length - 1; i >= 0; i--)
					{
						if (i >= exp.length - temp.length)
						{
							exp[i] = temp[i - (exp.length - temp.length)];
						}
						else
						{
							exp[i] = new Integer(0).byteValue();
						}
					}
				}
				else
				{
					exp = temp.clone();
				}

				// 需要决定使用什么算法
				// 随机决定！！！
				// 非对称算法
				byte cipherAlgorithm = H5BaseCipherChannelHandler.randomCipherAlgorithm();
				// hmac算法
				byte hmacAlgorithm = H5BaseCipherChannelHandler.randomHmacAlgorithm();

				cipherHandler.setParameter(CipherConnectionConstant.PARA_KEY_CIPHER_ALGO, cipherAlgorithm);
			
				cipherHandler.setParameter(CipherConnectionConstant.PARA_KEY_HMAC_ALGO, hmacAlgorithm);

				// 发送RSA的Key的消息
				RSAPublicKeyRecord rsaKeyRecord = new RSAPublicKeyRecord(publicModulus, exp,
					cipherAlgorithm, hmacAlgorithm);

				cipherHandler.sendData(rsaKeyRecord.resolve(), true);

				//System.out.println("handShake finish!");
			}
		}
	}

	@Override
	public void sendHandle(CipherHandler cipherHandler)
	{
		cipherHandler.passMessage(CipherHandler.PASS_MESSAGE_SEND);
	}

}
